/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 * <p>
 * https://www.renren.io
 * <p>
 * 版权所有，侵权必究！
 */

package com.piggy.oss.cloud;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.Protocol;
import com.aliyun.oss.model.OSSObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.piggy.common.core.exception.base.BaseException;
import com.piggy.common.core.constant.OssConstans;
import lombok.SneakyThrows;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 阿里云存储
 *
 * @author piggy piggy@piggy.com
 */
public class AliyunCloudStorageService extends CloudStorageService {
	private OSSClient client;

	public AliyunCloudStorageService(CloudStorageConfig config) {
		this.config = config;

		//初始化
		init();
	}

	private void init() {
		client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(),
			config.getAliyunAccessKeySecret());
	}

	@Override
	public String upload(byte[] data, String path) {
		return upload(new ByteArrayInputStream(data), path);
	}

	@Override
	public String upload(InputStream inputStream, String path) {
		try {
			client.putObject(config.getAliyunBucketName(), path, inputStream);
		} catch (Exception e) {
			throw new BaseException("上传文件失败，请检查配置信息", e.getMessage());
		}

		return path;
	}

	@Override
	public String uploadSuffix(byte[] data, String suffix) {
		return upload(data, getPath(config.getAliyunPrefix(), suffix));
	}

	@Override
	public String uploadSuffix(InputStream inputStream, String suffix) {
		return upload(inputStream, getPath(config.getAliyunPrefix(), suffix));
	}

	@Override
	public String buildUrl(String path) {
		AssumeRoleResponse response = getStsSecret();
		URL url = getUrl(response.getCredentials().getAccessKeyId(), response.getCredentials().getAccessKeySecret(), response.getCredentials().getSecurityToken(), path);
		return URLUtil.normalize(url.toString());
//		return getHttpsUrlByUrl(url);
	}

//	public String getHttpsUrlByUrl(URL url){
//		String httpsUrl=url.toString();
//		httpsUrl="https"+httpsUrl.substring(4);
//		return httpsUrl;
//	}

	@Override
	public List<String> buildUrlList(List<String> objectNameList) {
		AssumeRoleResponse response = getStsSecret();
		List<String> listUrl = new ArrayList<>();
		for(int i=0; i<objectNameList.size(); i++){
			URL url = getUrl(response.getCredentials().getAccessKeyId(), response.getCredentials().getAccessKeySecret(), response.getCredentials().getSecurityToken(), objectNameList.get(i));
			listUrl.add(url.toString());
//			listUrl.add(getHttpsUrlByUrl(url));
		}
		return listUrl;
	}

	@Override
	public void delFile(String objectName) {

		// 删除文件或目录。如果要删除目录，目录必须为空。
		client.deleteObject(config.getAliyunBucketName(), objectName);
	}

	@SneakyThrows
	@Override
	public byte[] downloadFile(String objectName) {
		OSSObject ossObject = client.getObject(config.getAliyunBucketName(), objectName);
		InputStream inputStream = ossObject.getObjectContent();
		byte[] byt = IoUtil.readBytes(inputStream);
		ossObject.close();
		return byt;
	}

	private AssumeRoleResponse getStsSecret() {
		//构建一个阿里云客户端，用于发起请求。
		//构建阿里云客户端时需要设置AccessKey ID和AccessKey Secret。
		DefaultProfile profile = DefaultProfile.getProfile(OssConstans.REGIONID, config.getAliyunAccessKeyId(), config.getAliyunAccessKeySecret());
		IAcsClient client = new DefaultAcsClient(profile);

		//构造请求，设置参数。关于参数含义和设置方法，请参见API参考。
		AssumeRoleRequest request = new AssumeRoleRequest();
		request.setRegionId(OssConstans.REGIONID);
		request.setRoleArn(config.getRoleArn());
		request.setRoleSessionName(OssConstans.ROLESESSIONNAME);
		AssumeRoleResponse response;
		//发起请求，并得到响应。
		try {
			response = client.getAcsResponse(request);
			return response;
		} catch (ServerException e) {
			throw new BaseException(e.getMessage());
		} catch (ClientException e) {
			System.out.println("ErrCode:" + e.getErrCode());
			System.out.println("ErrMsg:" + e.getErrMsg());
			System.out.println("RequestId:" + e.getRequestId());
			throw new BaseException(e.getMessage());
		}
	}

	private URL getUrl(String accessKeyId, String accessKeySecret, String securityToken, String objectName) {
		//配置HTTPS
		ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
		clientBuilderConfiguration.setProtocol(Protocol.HTTPS);
		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(config.getAliyunEndPoint(), accessKeyId, accessKeySecret, securityToken,clientBuilderConfiguration);
		// 设置签名URL过期时间为3600秒（1小时）。
		Date expiration = new Date(new Date().getTime() + OssConstans.CLOUD_FILE_EXPIRATION);
		// 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
		URL url = ossClient.generatePresignedUrl(config.getAliyunBucketName(), objectName, expiration);
		ossClient.shutdown();
		return url;
	}
}
